package org.jeecg.modules.workflow.service.definition;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.exception.util.ServiceExceptionUtil;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.json.JsonUtils;
import org.jeecg.common.workflow.vo.definition.form.BpmFormCreateReqVO;
import org.jeecg.common.workflow.vo.definition.form.BpmFormPageReqVO;
import org.jeecg.common.workflow.vo.definition.form.BpmFormUpdateReqVO;
import org.jeecg.modules.workflow.convert.definition.BpmFormConvert;
import org.jeecg.modules.workflow.entity.BpmForm;
import org.jeecg.modules.workflow.enums.ErrorCodeConstants;
import org.jeecg.modules.workflow.mapper.BpmFormMapper;
import org.jeecg.modules.workflow.service.definition.dto.BpmFormFieldRespDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.validation.Valid;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 工作流的单定义Service业务层处理
 *
 * @author whnk
 * @date 2022-04-20
 */
@Service
public class BpmFormServiceImpl implements BpmFormService
{
    @Autowired
    private BpmFormMapper bpmFormMapper;

    @Autowired
    private BpmFormConvert bpmFormConvert;


    @Override
    public String createForm(@Valid BpmFormCreateReqVO createReqVO) {
        this.checkFields(createReqVO.getFields());
        // 插入
        BpmForm form = bpmFormConvert.convert(createReqVO);
        form.setCreateBy(getUserName());
        form.setCreateTime(new Date());
        bpmFormMapper.insert(form);
        // 返回
        return form.getId();
    }

    @Override
    public void updateForm(@Valid BpmFormUpdateReqVO updateReqVO) {
        this.checkFields(updateReqVO.getFields());
        // 校验存在
        this.validateFormExists(updateReqVO.getId());
        // 更新
        BpmForm updateObj = bpmFormConvert.convert(updateReqVO);
        updateObj.setUpdateBy(getUserName());
        updateObj.setUpdateTime(new Date());
        bpmFormMapper.updateById(updateObj);
    }

    @Override
    public void deleteForm(String id) {
        // 校验存在
        this.validateFormExists(id);
        // 删除
        BpmForm updateObj = new BpmForm();
        updateObj.setId(id);
        updateObj.setDeleted(1);
        updateObj.setUpdateBy(getUserName());
        updateObj.setUpdateTime(new Date());
        bpmFormMapper.deleteById(updateObj);
    }

    @Override
    public BpmForm getForm(String id) {
        return bpmFormMapper.selectById(id);
    }

    @Override
    public List<BpmForm> getFormList() {
        LambdaQueryWrapper<BpmForm> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BpmForm::getDeleted, 0);
        return bpmFormMapper.selectList(queryWrapper);
    }

    @Override
    public IPage<BpmForm> getFormPage(BpmFormPageReqVO pageReqVO) {
        return bpmFormMapper.selectPage(pageReqVO);
    }

    /**
     * 校验 Field，避免 field 重复
     *
     * @param fields field 数组
     */
    private void checkFields(List<String> fields) {
        Map<String, String> fieldMap = new HashMap<>(); // key 是 vModel，value 是 label
        for (String field : fields) {
            BpmFormFieldRespDTO fieldDTO = JsonUtils.parseObject(field, BpmFormFieldRespDTO.class);
            Assert.notNull(fieldDTO);
            String oldLabel = fieldMap.put(fieldDTO.getVModel(), fieldDTO.getLabel());
            // 如果不存在，则直接返回
            if (oldLabel == null) {
                continue;
            }
            // 如果存在，则报错
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_FIELD_REPEAT, oldLabel, fieldDTO.getLabel(), fieldDTO.getVModel());
        }
    }

    private void validateFormExists(String id) {
        if (bpmFormMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.FORM_NOT_EXISTS);
        }
    }

    @Override
    public List<BpmForm> getFormList(List<Long> ids) {
        return bpmFormMapper.selectBatchIds(ids);
    }

    private String getUserName()
    {
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        return sysUser.getRealname();
    }

}
